home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1997 July: Mac OS SDK / Dev.CD Jul 97 SDK2.toast / Development Kits (Disc 2) / ScriptX / Documentation / Code Examples from Docs / compguid / doctemp / docdev / docfns.sx next >
Encoding:
Text File  |  1996-05-21  |  19.5 KB  |  626 lines  |  [TEXT/ttxt]

  1. --<<<-
  2. -- Filename:DocDemo.sx
  3.  
  4. -- Other Files Required:
  5. --         seadoc.sxt (if you want to see the sample document)
  6.  
  7. -- Purpose: 
  8. --        The functions in docfns.sx create a document that can have two
  9. --        kinds of pages: a definiton page and a movie page.
  10. --        You can move through the pages in the document by clicking on
  11. --        bars at the side of each page.
  12. --        A definition page has a heading, description and picture.
  13. --        A movie page has a heading, description, movie, and copyright info
  14. --         and also play and stop buttons for controlling the movie.
  15.  
  16. --        A document of this kind can be created for any set of input 
  17. --        objects that conform to the standards required by the document.
  18. --        For a movie page, the input object must have heading,
  19. --        description, movie and copyrightInfo ivs. 
  20. --         Heading, description, and copyrightInfo
  21. --         ivs must contain Text.
  22. --        Picture iv must contain a bitmap.
  23. --        For a definition page, the input object must have heading,
  24. --        description and picture ivs. Heading and description 
  25. --        ivs must contain Text.
  26. --        Movie iv must contain an interleaved movie player.        
  27.  
  28. -- Specialized Classes:
  29. --        SpecialPage has an iv that has a dataObject iv that points to 
  30. --        the object holding the data for this page.
  31. --        MoviePushButton has an iv that points to the movie player
  32. --        controlled by the pushbutton.
  33. --        MyDocument has a currentMovie iv that knows which movie
  34. --        is currently playing, if any
  35.  
  36. -- Instructions to User:
  37. --        Load docfns.sx, create the objects to hold the data for the
  38. --        pages, then call makeDocument to create a document. Append the
  39. --        document to an open window and call "goto docname 1" 
  40. --        to open the first page.
  41. --        Click on the bar on the right hand side of the page to move
  42. --         to the next page, and click on the bar on the left hand side of
  43. --        the page to move to the previous page.
  44.  
  45. --        Alternatively load makeDoc.sx, which files in docfns.sx
  46. --        then calls createDoc1, whch calles makeDocument,
  47. --         to make a sample document and save it in seadoc.sxt.
  48.  
  49.  
  50.  
  51.  
  52.  
  53.  
  54. -- Author:
  55. --        Jocelyn Becker.
  56. --         Modified on: 11/13/95 to update to 1.5
  57.  
  58. ------------------------------------------------------------------------
  59.  
  60. -- Document Templates Test
  61.  
  62.  
  63.  
  64. -- Define some custom colors
  65.  
  66.  
  67. global constant blueBrush := new brush color: blueColor
  68. global constant skyBlueBrush := new brush \
  69.     color: (new RGBColor red:80 green:180 blue:250)
  70. global constant darkerBlueBrush := new brush \
  71.     color:(new RGBColor red:20 green:120 blue:250)
  72. global constant otherBlueBrush := new brush \
  73.     color:(new RGBColor red:140 green:180 blue:250)
  74. global constant greenBrush := new brush color: greenColor
  75. global constant middleGreenBrush:= new brush \
  76.     color:(new RGBColor red:160 green:250 blue:160)
  77.  
  78.  
  79.  
  80.  
  81.  
  82.  
  83. -- Make the background layer
  84. -- This layer contains the outline of the page, the bars  
  85. -- on the left and right that let you move through the document,  
  86. -- and also text presenters for the heading for the page and the page number.
  87. -- pageWidth and pageHeight are the width and height of the page.
  88.  
  89. -- the margin is the distance between the edge of the page
  90. -- and any content (such as the back/forward buttons)
  91. -- the innerMargin is the margin at which contents other
  92. -- than the back/forward buttons start
  93.  
  94. function makeMargin pageWidth -> (pageWidth * 0.1)
  95. function makeInnerMargin pageWidth -> (pageWidth * 0.22)
  96.  
  97.  
  98. function makeBackgroundLayer pageWidth pageHeight ->
  99. (
  100.     local margin      := makeMargin pageWidth
  101.     local innerMargin := makeInnerMargin pageWidth
  102.     
  103.     -- the smallwidth is the width of the back and forward
  104.     -- buttons and the pageNumber element
  105.     local smallwidth  := (innermargin - margin) * 0.66
  106.     
  107.     local smallRect   := new rect x1:0 y1:0 x2:smallwidth y2:smallwidth
  108.     
  109.     
  110.     -- Create a Text Presenter that holds the pagenumber
  111.     
  112.     local pageNumberText := (new TextPresenter \
  113.             boundary: smallRect stroke:greenBrush \
  114.             fill: middleGreenBrush \
  115.             target: ("" as Text))
  116.         pageNumberText.inset := new point x:0 y:2
  117.         setDefaultAttr pageNumberText @font \ 
  118.                 (new PlatformFont name:"Palatino")
  119.         setDefaultAttr pageNumberText @size 12
  120.         setDefaultAttr pageNumberText @alignment  @center
  121.     
  122.     
  123.     -- Find the page number. 
  124.     -- The document's cursor indicates 
  125.     -- the current position in the doc
  126.     
  127.     local pageNumberElement := new pageElement\
  128.          presenter: pageNumberText \
  129.             target: (e -> (findParent e Document).cursor as Text )
  130.         pageNumberElement.x := (pageWidth - smallWidth) / 2
  131.         pageNumberElement.y := pageHeight - (margin + smallWidth)
  132.     
  133.     
  134.     -- Create the Text Presenter for the heading
  135.     local headingText := (new TextPresenter \
  136.             boundary: (new rect \
  137.                 x2:(pageWidth - (2 * innerMargin)) y2:35) \
  138.             stroke: blackBrush target: ("" as Text) \
  139.             fill: skyBlueBrush)
  140.         headingText.inset := new point x:10 y:10
  141.         setDefaultAttr headingText @font   \ 
  142.             (new PlatformFont name:"Helvetica")
  143.         setDefaultAttr headingText @size 18
  144.         setDefaultAttr headingText @alignment @center
  145.     
  146.     local headingElement := new pageElement presenter: headingText \
  147.             target: (e -> getfirst (getParentData e SpecialPage))
  148.         headingElement's x := innerMargin 
  149.         headingElement's y := margin
  150.     
  151.     
  152.     
  153.     -- Create the forward and backward page buttons
  154.     local buttonrect := new rect x2:smallwidth \
  155.         y2:(pageHeight - (2 * margin))
  156.     
  157.     local forwardUp := new twoDshape boundary: buttonRect \
  158.                     fill: skyBlueBrush stroke: otherBlueBrush
  159.     local forwardDown := new twoDshape boundary: buttonRect \
  160.                     fill: darkerBlueBrush 
  161.     
  162.     local backwardUp := new twoDshape boundary: buttonRect \
  163.                     fill: skyBlueBrush stroke: otherBlueBrush
  164.     local backwardDown := new twoDshape boundary: buttonRect \
  165.                     fill: darkerBlueBrush 
  166.     
  167.     
  168.     local forwardButton := new pushbutton \
  169.         releasedPresenter:forwardUp \
  170.         pressedPresenter: forwardDown
  171.     local backwardButton := new pushbutton \
  172.         releasedPresenter:backwardup \
  173.         pressedPresenter: backwarddown
  174.         
  175.     -- When a pushbutton is pressed, its activateAction function is called
  176.     -- with the arguments pushbutton.authordata and pushbutton.
  177.     -- Here we want to find the document containing the pushButton,
  178.     -- so call findParent on the object that is presenting the pushbutton 
  179.     
  180.     forwardButton.activateAction := \
  181.             (a b -> forward (findParent (b.presentedBy) Document)) 
  182.     
  183.     backwardButton.activateaction := \
  184.             (a b -> backward (findParent (b.presentedBy) Document))
  185.     
  186.     
  187.     -- put the push buttons inside page elements
  188.     local forwardButtonElement := new pageelement \
  189.         presenter: forwardButton 
  190.     forwardButtonElement.x := (pageWidth - (margin + smallwidth)) 
  191.     forwardButtonElement.y := margin
  192.     
  193.     local backwardButtonElement := new pageelement \
  194.         presenter:backwardButton
  195.     backwardButtonElement.x := margin
  196.     backwardButtonElement.y := margin
  197.     
  198.     -- Create a pagelayer that holds background information
  199.     local bkgdLayer := new pagelayer \
  200.         boundary:(new rect x2:pageWidth y2:pageHeight)
  201.  
  202.     bkgdLayer.stroke := blueBrush
  203.     append bkgdLayer pageNumberElement
  204.     append bkgdLayer forwardButtonElement
  205.     append bkgdLayer backwardButtonElement
  206.     append bkgdLayer headingElement
  207.     
  208.     
  209.     -- Make an actuator controller to control 
  210.     -- the buttons in the background layer
  211.     local docController := new actuatorController space:bkgdLayer
  212.     
  213.     append doccontroller forwardButtonElement
  214.     append doccontroller backwardButtonElement
  215.         
  216.     -- return the background layer
  217.     bkgdLayer
  218. )
  219.  
  220. print "made the backgroundlayer function"
  221. -- Make the definition layer, which contains text definition
  222.  
  223. function makeDefinitionLayer pageWidth pageHeight->
  224. (
  225.     local margin      := makeMargin pageWidth
  226.     local innerMargin := makeInnerMargin pageWidth
  227.  
  228.     -- Create the Text Presenter that presents the info
  229.     local infoText := (new TextPresenter \
  230.         boundary: (new rect x2: (pageWidth - (2 * innerMargin)) y2: 80) \
  231.         stroke:blackbrush target:("" as Text))
  232.         
  233.     infoText.inset := new point x:10 y:10
  234.     setDefaultAttr  infoText @font \ 
  235.             (new PlatformFont name:"Palatino")
  236.     setDefaultAttr infoText @size   12
  237.     setDefaultAttr infoText @leading  14
  238.     setDefaultAttr infoText @alignment  @flush
  239.  
  240.      
  241.     -- put the info text presenter into a page element
  242.     local infoElement := new pageElement presenter : infoText \
  243.             target: (e -> getsecond (getParentData e SpecialPage))
  244.     infoElement.x := innerMargin
  245.     infoElement.y := innermargin + 15 
  246.     
  247.     -- create a page layer
  248.     local definitionLayer := new pagelayer \
  249.         boundary:(new rect x2:pageWidth y2:pageHeight)
  250.     append definitionLayer infoElement
  251.     
  252.     -- return the definition page layer
  253.     definitionLayer
  254. )
  255.  
  256. print "made makeDefinitionLayer"
  257.  
  258. -- Make the picture layer
  259. function makePictureLayer pageWidth pageHeight ->
  260. (
  261.     local margin      := makeMargin pageWidth
  262.     local innerMargin := makeInnerMargin pageWidth
  263.  
  264.     -- Create the box that displays the picture
  265.     local picPresenter := \
  266.             new TwoDShape fill:blackbrush stroke:blackbrush
  267.  
  268.     
  269.     local picElement := \
  270.         new pageElement presenter: picPresenter \
  271.             target: (e -> getThird (getParentdata e SpecialPage))
  272.         picElement.x := innerMargin
  273.         picElement.y := 160 + margin
  274.  
  275.     -- Make a page layer for the picture
  276.     local pictureLayer := new pagelayer \
  277.             boundary:(new rect x2:pageWidth y2:pageHeight)
  278.     
  279.     append pictureLayer picElement
  280.     
  281.     -- return the picture layer
  282.     pictureLayer
  283. )
  284.  
  285. print "made makePictureLayer"
  286.  
  287. -- define a subclass of Document
  288. -- this document knows what movie,
  289. -- if any, is currently playing
  290. class MyDocument (Document)
  291. instance variables 
  292.      currentMovie
  293. end
  294.  
  295.  
  296.  
  297.  
  298. -- Make a class for the Pushbutton that controls the movie
  299.  
  300. class MoviePushbutton (PushButton)
  301.     instance variables
  302.         movieElement
  303. end
  304.  
  305. -- Define the methods used by the movie button
  306.  
  307. method playMovie button {class MoviePushButton} ->   
  308. (
  309.     -- the movieElement is the first element in the group space
  310.     local thisMovieElement := button.movieElement
  311.     local doc := findparent thisMovieElement.presentedBy Document
  312.     local movie := thisMovieElement[1]
  313.   
  314.     stop movie
  315.     gotobegin movie
  316.     playprepare movie 1
  317.     play movie
  318.     
  319.     -- keep track of which movie is currently playign
  320.     doc.currentMovie := movie
  321. )
  322.  
  323.  
  324. method stopMovie button {class MoviePushButton} -> 
  325. (
  326.     -- the movie is the first element in the group space
  327.     local thisMovieElement := button.movieElement
  328.     local doc := findparent thisMovieElement.presentedBy Document
  329.     
  330.     local movie := thisMovieElement[1]
  331.     stop movie
  332.     gotobegin movie
  333.     playprepare movie 1
  334.     
  335.     -- no movie is currently playing
  336.     doc.currentMovie := undefined
  337. )
  338.  
  339. print "Defined the MoviePushButton class"
  340.  
  341. class MovieGroupSpace (GroupSpace)
  342. end
  343.  
  344. -- define the target setter for MovieGroupSpace
  345. -- so that when you add a value to the target iv
  346. -- it effectively adds the target to the group
  347.  
  348. method targetSetter self {class MovieGroupSpace} value ->
  349. (    emptyout self
  350.      prepend self value
  351.  )
  352.  
  353.  
  354. -- define the getter also
  355. method targetGetter self {class MovieGroupSpace} ->
  356. (self[1] )
  357.  
  358. print "Defined the MovieGroupSpace class"
  359.  
  360.  
  361.  
  362. -- Make a pagelayer for the movie.
  363. -- This layer contains the movie element and the buttons 
  364. -- to control the movie.
  365.  
  366. function makeMovieLayer pageWidth pageHeight ->
  367. (
  368.     local margin      := makeMargin pageWidth
  369.     local innerMargin := makeInnerMargin pageWidth
  370.     local buttonWidth  := 35
  371.     local buttonHeight := buttonWidth * 0.75
  372.  
  373.      
  374.     local movieElement := new pageElement \
  375.         presenter: (new MovieGroupSpace) \
  376.         target: (e -> (getNth (getParentdata e SpecialPage) 3))
  377.     movieElement.x := innerMargin
  378.     movieElement.y := 160 + margin 
  379.  
  380.     -- Create the Movie Control Buttons    
  381.     local movieButtonRect := new rect x2: buttonWidth y2: buttonHeight
  382.     
  383.     local playUp := new textPresenter boundary: movieButtonRect \
  384.             fill: otherBlueBrush stroke: BlueBrush \
  385.             target: ("Play" as Text)         
  386.     playUp.inset := new point x:0 y:4
  387.     setDefaultAttr playUp @font  (new PlatformFont name:"Helvetica")
  388.     setDefaultAttr playUp @alignment  @center
  389.     
  390.     local playdown := new twoDshape \
  391.             boundary:movieButtonRect \
  392.             fill:darkerBlueBrush 
  393.     
  394.     -- Create the pushbutton to play the movie.
  395.     
  396.     local playButton:= new MoviePushbutton \
  397.             releasedPresenter: playUp pressedPresenter: playdown
  398.     playButton.movieElement := movieElement
  399.  
  400.     -- When a push button is pressed, 
  401.     -- its activateAction function is called
  402.     -- with the arguments pushbutton.authorData and pushbutton.
  403.     -- Here we want to call the playMovie function on the pushbutton
  404.  
  405.     playButton.activateAction := (a b -> playMovie b)
  406.     
  407.     playButton.x := innerMargin 
  408.     playButton.y := (pageHeight -  margin - playbutton.height ) 
  409.         
  410.     -- make the shadow for the playButton
  411.     local playShadow := new twodshape fill: darkerBlueBrush \
  412.             stroke: darkerBlueBrush target: movieButtonRect
  413.     playShadow.x := playButton.x + 2
  414.     playShadow.y := playButton.y - 2
  415.         
  416.     -- make the stop button
  417.     local stopUp := new textPresenter boundary:movieButtonRect \
  418.             fill: otherBlueBrush  stroke: BlueBrush  target: ("Stop" as Text)
  419.     setDefaultAttr stopUp @font   (new PlatformFont name:"Helvetica")
  420.     setDefaultAttr stopUp @alignment  @center
  421.     stopUp.inset := new point x:0 y:4
  422.     
  423.     local stopDown := new twoDshape boundary: movieButtonRect \
  424.             fill: darkerBlueBrush 
  425.     
  426.     local stopButton := new MoviePushbutton \
  427.             releasedPresenter: stopUp  pressedPresenter: stopDown
  428.     stopButton.movieElement   := movieElement
  429.     stopButton.activateaction := (a b -> stopmovie b)
  430.     stopButton.x := (pageWidth - (innerMargin + buttonWidth))
  431.     stopButton.y := pageHeight - stopbutton.height - margin
  432.     
  433.     -- make the shadow for the stop button
  434.     local stopShadowButton := new twoDshape fill: darkerBlueBrush \
  435.             stroke: darkerBlueBrush  target: movieButtonRect
  436.     stopShadowButton.x := stopButton.x + 2
  437.     stopShadowButton.y := stopButton.y - 2
  438.         
  439.     -- make a box to show any required copyright notices
  440.     local copyRightBox := new TextPresenter \
  441.         boundary:(new rect \
  442.             x2: (pagewidth -  innermargin) y2:15) \
  443.             target:""
  444.     setdefaultAttr copyRightBox @font (new PlatformFont name:"Times")
  445.     setdefaultAttr copyRightBox @size 11
  446.     
  447.     -- put the copy right text presenter into a page element
  448.     local copyrightElement := new pageElement presenter: copyRightBox \
  449.             target: (e -> (getNth (getParentdata e SpecialPage) 4)) 
  450.             
  451.     copyrightElement.x := innermargin 
  452.     copyrightElement.y := pageheight - 20
  453.     
  454.     -- Make a page layer for the moviepage
  455.     local movieLayer := new PageLayer \
  456.         boundary:(new rect x2:pageWidth y2:pageHeight)
  457.     append movieLayer movieElement
  458.     append movieLayer playButton
  459.     append movieLayer stopButton
  460.     append movieLayer playShadow
  461.     append movieLayer stopShadowButton
  462.     prepend movieLayer copyrightElement
  463.     
  464.     -- Make an actuator controller to control the buttons
  465.     -- on the movieLayer
  466.     
  467.     local movieController := new actuatorController space:movieLayer
  468.     append movieController playButton
  469.     append movieController stopButton    
  470.     
  471.     -- return the movie layer
  472.     movieLayer
  473. )
  474.  
  475. -- Make a new Page subclass that points to the object 
  476. -- holding data for the page
  477. class SpecialPage (Page)
  478.     instance variables
  479.         dataObject
  480. end
  481.  
  482. print "defined the SpecialPage class"
  483.  
  484. -- define the changePage method for specialPage so
  485. -- that whenever the page changes, if a movie is
  486. -- playing, it stops automatically
  487. method changePage self {class SpecialPage} newpage ->
  488. (
  489.     local doc := findparent self document
  490.     if (doc.currentMovie != undefined) 
  491.         do (stop doc.currentmovie
  492.             doc.currentMovie := undefined
  493.             )
  494.     nextMethod self newpage
  495. )
  496.  
  497.  
  498.  
  499. print "made makeMovieLayer"
  500.  
  501.  
  502. -- makeTemplate makes a page template from a list of page layers
  503. -- Call this function with a list of the layers that make up the template
  504. -- It uses the boundary of the first layer in the list as the boundary
  505. -- for the page template
  506.  
  507. function makeTemplate layerList ->
  508. (
  509.     local template1 := new pageTemplate boundary:layerlist[1].boundary 
  510.     for i in layerList do append template1 i
  511.     template1
  512. )
  513.  
  514.  
  515. -- The following function adds a "movie page" to a document
  516. -- A "movie page" has a heading, description, movie 
  517. -- and buttons to control the movie
  518. -- The doc arg must be an existing document.
  519. -- The dataobject arg must be an object that has Text values in its
  520. -- heading and description instance variables, and whose
  521. -- movie instance variable must point to a target for a movie.
  522. -- The template arg must be a "movie page template", that is, 
  523. -- an object returned by the function makeTemplate, whose input collection
  524. -- is a background layer, a definition layer and a movie layer.
  525. -- These layers can in turn can be created by 
  526. -- the function makebackgroundlayer,
  527. -- makedefinitionlayer and makemovielayer respectively
  528. -- Note that you can use a single template object for multiple pages -
  529. -- you do not need to create a new one for each page
  530.  
  531. function appendMoviePage doc dataobject template ->
  532. (
  533.     -- The new page has the same boundary as its template
  534.     local newPage := new specialPage frame:template \
  535.             boundary:(template.boundary)
  536.     
  537.     -- Set the value of the page's dataobject instance variable
  538.     newpage.dataobject := dataobject
  539.     
  540.     -- Set the target of the page to be an anonymous function that 
  541.     -- returns an array of the heading, description and movie, 
  542.     -- which are found on the dataobject
  543.     newpage.target := (p -> #(p.dataObject.heading,
  544.                                 p.dataobject.description, 
  545.                                 p.dataobject.movie,
  546.                                 p.dataobject.copyrightInfo))
  547.     append doc newpage
  548.     -- return the new page
  549.     newpage
  550. )
  551.     
  552. -- The following function adds a "definition page" to a document.
  553. -- A "definition page" has a heading, a description and a bitmap
  554. -- The doc arg must be an existing document
  555. -- The dataobject must be an object that has Text values in its
  556. -- heading and description instance variables, and a 
  557. -- bitmap in its picture instance variable.
  558. -- The template arg must be a "definition template", that is ,
  559. -- an object returned by the makeTemplate function whose input 
  560. -- collection is a background layer, a definition layer and a picture layer
  561. -- which can be created by the functions makebackgroundlayer, 
  562. -- makedefinitionlayer and makepicturelayer respectively.
  563.  
  564. function appendDefinitionPage doc dataObject template ->
  565. (
  566.     -- The new page has the same boundary as its template
  567.     local newpage := new specialPage frame:template \
  568.             boundary:(template.boundary)
  569.     newpage.dataObject := dataObject
  570.     
  571.     -- Set the target of the page to be an anonymous function that 
  572.     -- returns an array containing the heading, description
  573.     -- and picture, which are found on the dataObject
  574.     newpage.target:= (p  -> #(p.dataObject.heading, 
  575.                                 p.dataObject.description, 
  576.                                 p.dataObject.picture))
  577.     append doc newpage
  578.     -- return the new page
  579.     newpage
  580. )
  581.  
  582. -- Example function that creates a document
  583. -- You would modify this to suit your needs
  584.  
  585. -- Note that you must generate the list of objects to use 
  586. -- as definitionObjectList and movieObjectList
  587.  
  588. -- definitionObjectList should be an array of objects
  589. -- that each have Text values in their heading and description
  590. -- instance variables, and a bitmap in their picture instance variable.
  591.  
  592. -- movieObjectList should be an array of objects
  593. -- that each have Text values in their heading and description
  594. -- instance variables, and a suitable target for a movieplayer
  595. -- in their movie instance variable.
  596.  
  597. -- pageWidth and pageHeight are the width and height of the page 
  598.  
  599.  
  600. function makeDocument pageWidth pageHeight \
  601.                 definitionObjectList movieObjectList ->
  602. (
  603.     -- Make the page layers
  604.     local bkgdLayer       := makeBackgroundLayer (pageWidth, pageHeight) 
  605.     local definitionLayer := makeDefinitionLayer (pageWidth, pageHeight)
  606.     local movieLayer      := makeMovieLayer (pageWidth, pageHeight)
  607.     local pictureLayer    := makePictureLayer (pageWidth, pageHeight)
  608.     
  609.     -- Make the page templates
  610.     local glossaryTemplate := \
  611.             makeTemplate #(pictureLayer, definitionLayer, bkgdLayer)
  612.     local movieTemplate := \
  613.             makeTemplate #(movieLayer, definitionLayer, bkgdLayer)
  614.     
  615.     -- Create the document and append pages to it.
  616.     local doc := new MyDocument
  617.     for i in definitionObjectList do
  618.         appendDefinitionPage doc i glossaryTemplate
  619.          
  620.     for i in movieObjectList do
  621.         appendMoviePage doc i movieTemplate
  622.     
  623.     -- returnt the document
  624.     doc
  625. )
  626.